gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/libsrc/ringdows/ringmenubar.cpp

    /**********************************************************************
//
//
//        ##########                          ######  #########   # ######    #
//      #############                      ########### ######### #########  ###
//     ######## # ###  ##                 ############# ##    ## #####  # ####
//     ####  ##    ## ###                 ###     ### # #      #####   #####
//          #     ###  #            #     ##       ##  ##      ##     ###
//         ## ###### ##      ##  ####    ####          #       #     ##
//       #########  ###  ## ### #######   ######      ##      ##    ###
//      ######      ##  ######  ##  ##       ####     #      ##     ####
//     #######     ##   ###### ##  ###          ##   ##     ###    ######
//     #########   ##  ###### ## ######         ### ##    ###      #  #####
//    ##    ###### ####### ### #### ##  ## #######  ########      ##    ####
//    ##      #### ###  #  ### ### ##  ##########   ######       ##      ####
//   ##         ##                ##   #########    ####         #         ##
//               #              ###
//                              ##
//                             ###
//                             ##
//
//
//							临风程序界面类库 ringdows.lib
//作者:临风
//
//版本:1.0
//
//声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到
//		  你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在
//		  修改的同时给作者一份同样的副本。
//		  本类库不得用于任何商业用途,如确实需要,请与作者联系。
//
//e-mail:ringphone@sina.com
//
//原文件名:ringmenubar.cpp
//
//本文件说明:菜单栏实现代码。
//
//几个尺寸说明:
//		扩展尺寸 - 	系统图标,最小/大化,关闭等系统按钮的尺寸,该尺寸视
//						状态可为0或实际尺寸
//		m_BarSize - 菜单栏包围尺寸,包括扩展尺寸紧密排列后的包围矩形尺寸。
//		m_fSize -	浮动时的包围尺寸。
//		m_BtnsSize - 按钮和扩展尺寸排列成一行/列时的宽/高。
//		m_WndSize - 实际窗口尺寸
//		m_SingleSize - 单行/列时的高/宽
//
**********************************************************************/

#define MAKE_SELF_LIB
#include "ringdows.h"

RingMenuBar::RingMenuBar()
{
   m_hWnd = NULL;
   m_windowType = ITIS_MENUBAR;
	m_rm = NULL;
	m_rmsys = NULL;
	m_sysIcon = NULL;
	m_hbmSys = NULL;
	m_bShowIcon = FALSE;
	m_nCapedExtButton = 0;
	m_nPopupedMenu = m_nHotButton = -1;
	m_ExStyle = TBS_EX_DOCKABLE;
	SetRectEmpty(&m_rcSysBtn);
	m_item = NULL;
	m_nBtnCount = m_BtnAllocCnt = 0;
	m_dockbar = NULL;
	m_fSize.cx = m_fSize.cy = 0;
	m_SingleSize.cx = m_SingleSize.cy = 0;
	m_nMinWidth = 0;
}

RingMenuBar::~RingMenuBar()
{
	delete m_rmsys;
	FreeMenuItems();
	if(m_hbmSys)
		DeleteObject(m_hbmSys);
}

BOOL RingMenuBar::Create(LPCTSTR szTitle,int dockStyle/*=TBS_EX_DOCKABLE*/,
								 int dockState/*=TBS_FLAG_DOCKTOP*/)
{
	if(IsWindow())
		return TRUE;
	
	WNDCLASSEX wndclsex =
   {
		sizeof(WNDCLASSEX),
			CS_PARENTDC,//CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW,
			InitWndProc,
			0,//sizeof(RingBaseWnd*),
			0,//sizeof(RingBaseWnd*),
			GetInstance(),
			NULL,
			NULL,
			(HBRUSH)NULL,//(COLOR_BTNFACE + 1),
			NULL,
			"RingMenuBar",
			NULL
   };
	
	if(!RegRingdowClass(&wndclsex))
		return NULL;
	
	m_BarSize.cx = m_WndSize.cx = 0;
	m_BarSize.cy = m_WndSize.cy = 0;
	m_BtnsSize.cx = m_BtnsSize.cy = 0;

	CreateEx(szTitle,"RingMenuBar",
		WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
		0/*WS_EX_TOOLWINDOW*/,NULL,NULL,0,0,0,0);

	Show(SW_SHOW);
	
	m_dockbar = EnableDock(szTitle,dockStyle|TBS_EX_ALLLINE,dockState);
	return (BOOL)m_hWnd;
}

//注意:hMenu不能是其他ringCoolMenu对象的成员,否则
//RingMenuBar::Attach后两个对象对同一个hMenu操作,后果不确定
BOOL RingMenuBar::LoadMenu(HMENU hMenu/*=NULL*/,BOOL bRemove/*=TRUE*/)
{	
	if(hMenu == NULL)
		m_rm = ((RingWnd*)m_parent)->InstallCoolMenu();
	else
	{
		if(m_rm == NULL)
			m_rm = new RingCoolMenu;

		if(m_rm)
			m_rm->Attach(hMenu);
	}
	return LoadMenu(m_rm,bRemove);
}

BOOL RingMenuBar::LoadMenu(RingCoolMenu* rm,BOOL bRemove/*=TRUE*/)
{	
	if(m_rm == NULL)
		if(rm)
			m_rm = rm;
		else
			return FALSE;

	if(Create(LANSTR_MENUBARNAME))
	{
		if(m_font.GetFont() == NULL)
			m_font.SetFont((HFONT)GetStockObject(DEFAULT_GUI_FONT));
			
		if(m_vfont.GetFont() == NULL)
		{
			LOGFONT lf;
			if(m_font.GetLogFont(&lf))
			{
				lf.lfEscapement = 2700;
				m_vfont.SetFont(&lf);
			}
		}
		if(m_dockbar && m_dockbar->IsVert())
			m_vfont.SetWindowFont(m_hWnd);
		else
			m_font.SetWindowFont(m_hWnd);

		if(!MakeMenuButtons())
			return FALSE;
			
		if(bRemove)
			::SetMenu(m_parent->Handle(),NULL);

		if(m_parent->GetWindowType() == ITIS_MDIFRAME && m_hbmSys == NULL)
		{
			//MDI菜单栏,需要初始化最小,还原,关闭按钮
			ringFont rf("Marlett",9);
			HDC hMDC = GetDC(GetDesktopWindow());
			HDC hDC = CreateCompatibleDC(hMDC);
			//字体大小12,最小,还原,关闭按钮紧密排列共宽36,
			//一起显示到菜单栏作为一幅图象该图象宽50(关闭按钮与
			//前一按钮空2像素,每一按钮16*14。36+50=86)
			m_hbmSys = CreateCompatibleBitmap(hMDC,86,14);
			SelectObject(hDC,m_hbmSys);
				
			::SetBkColor(hDC,0x00FFFFFF);
			::SetTextColor(hDC,0L);
			RECT rc = {0,0,36,12};
			SelectObject(hDC,rf.GetFont());
			DrawText(hDC,"02r",-1,&rc,DT_LEFT);
			DeleteDC(hDC);
			ReleaseDC(GetDesktopWindow(),hMDC);
			SetRect(&m_rcSysBtn,0,3,50,17);
			if(m_parent->GetWindowType() == ITIS_MDIFRAME)
				((RingMDIFrameWnd*)m_parent)->SetMenuBar(this);
		}
		return TRUE;
	}
	return FALSE;
}

BOOL RingMenuBar::MakeMenuButtons()
{
	if(m_rm == NULL)
		return FALSE;

	int i,cnt;//,nStr;
	char menutext[80];
		
	cnt = GetMenuItemCount(m_rm->GetMenu());
	if(!AllocMenuItems(cnt))		
		return FALSE;

	MENUITEMINFO mi;
	DWORD data;
	UINT state;
	int index = 0;

	for(i=0;i<cnt;i++)
	{
		memset(&mi,0,sizeof(MENUITEMINFO));
		mi.cbSize = sizeof(MENUITEMINFO);
		mi.fMask = MIIM_ID | MIIM_STATE | MIIM_SUBMENU;

		memset(menutext,0,80);
		GetMenuString(m_rm->GetMenu(),i,menutext,80,MF_BYPOSITION);
	
		GetMenuItemInfo(m_rm->GetMenu(),i,TRUE,&mi);
		
		state = (mi.fState == MFS_DISABLED)?TBSTATE_INDETERMINATE:TBSTATE_ENABLED;
		if(mi.hSubMenu)
		{
			data = index | 0xFFFFFF00;
			index ++;
		}
		else
			data = mi.wID;

		if(!AddButton(menutext,state,data))
			return FALSE;
	}
	return TRUE;
}

BOOL RingMenuBar::AllocMenuItems(int cnt)
{
	cnt ++;
	if(cnt > 0)
	{
		LPRINGMENUBARITEM tmp = m_item;
		if(m_item && cnt > m_BtnAllocCnt)
		{
			m_item = (LPRINGMENUBARITEM)GlobalReAlloc(m_item,sizeof(RINGMENUBARITEM)*cnt,GMEM_MOVEABLE);
			if(m_item == NULL)
			{
				m_item = tmp;
				return FALSE;
			}
			else
				m_BtnAllocCnt = cnt;
		}
		else if(m_item == NULL)
		{
			m_item = (LPRINGMENUBARITEM)GlobalAlloc(GPTR,sizeof(RINGMENUBARITEM)*cnt);
			m_BtnAllocCnt = cnt;
		}
		return (BOOL)m_item;
	}
	else
		return FALSE;
}

void RingMenuBar::FreeMenuItems()
{
	LPRINGMENUBARITEM tmp = m_item;	
	try
	{
		if(tmp)
			for(int i=0;i<m_nBtnCount;i++)
			{
				Del((LPSTR)tmp->m_text);
				tmp ++;
			}
	}
	catch(...)
	{
	}
	GlobalFree(m_item);
	m_item = NULL;
}

BOOL RingMenuBar::AddButton(LPCTSTR szText,int state,DWORD dwData)
{
	if(m_item == NULL)
		return FALSE;

	int index;
	
	for(index=0;index<m_nBtnCount;index++)
	{
		if(m_item[index].m_state == 0)
			break;	
	}
	if(index >= m_BtnAllocCnt && !AllocMenuItems(index + 2))
		return FALSE;

	if(szText)
	{
		m_item[index].m_text = (LPTSTR)New(strlen(szText)+2);
		if(m_item[index].m_text)
			wsprintf(m_item[index].m_text,szText);
	}
	m_item[index].m_state = state;
	m_item[index].m_data = dwData;
	m_item[index].m_id = index;

	m_nBtnCount ++;
	return TRUE;	
}

BOOL RingMenuBar::InsertButton(int index,LPCTSTR szText,int state,DWORD dwData)
{
	index ++;
	if(index >= 0)
	{
		if(index >= m_nBtnCount && m_nBtnCount < m_BtnAllocCnt - 1)
			index = m_nBtnCount + 1;

		if(!AllocMenuItems(index))
			return FALSE;
				
		if(index <= m_nBtnCount)
			memmove(m_item + index + 1,m_item + index,
						sizeof(RINGMENUBARITEM)*(m_nBtnCount - (index - 1)));
		
		if(szText)
		{
			m_item[index].m_text = (LPTSTR)New(strlen(szText)+2);
			if(m_item[index].m_text)
				wsprintf(m_item[index].m_text,szText);
		}
		m_item[index].m_state = state;
		m_item[index].m_data = dwData;
		m_item[index].m_id = index;
		m_nBtnCount ++;
		return TRUE;
	}
	return FALSE;
}

//更新各按扭位置,计算当前状态的BarSize,WndSize,BtnsSize
//横向时需要根据窗口宽判断是否折行,竖向时不折行
void RingMenuBar::Update(int state)
{
	if(m_dockbar && m_item)
	{
		int index = 1,ext = EndSize();
		int nIconSize = PreSize();
		HDC hDC = GetDC(m_hWnd);	
		SIZE s;
		RECT rc = {0,0,0,0};

		if(state == -1)
			state = m_dockbar->GetState();

		if(IsVert(state))
		{
			SelectObject(hDC,m_vfont.GetFont());

			if(m_item->m_text)
			{
				s.cy = DrawText(hDC,m_item->m_text,
						strlen(m_item->m_text),&rc,
						DT_CALCRECT);
					//GetTextExtentPoint32(hDC,m_item->m_text,
					//	strlen(m_item->m_text),&s);
				s.cx = rc.right + 12;

				SetRect(&m_item->m_rect,0,nIconSize,s.cy + 8,nIconSize + s.cx);
			}
			m_BtnsSize.cy = m_BarSize.cy = s.cx + nIconSize;
			m_BarSize.cx = s.cy + 8;
			
			m_WndSize.cy = m_dockbar->GetClientHeight(0);

			for(;index<m_nBtnCount;index ++)
			{
				if(m_item[index].m_text)
				{
					s.cy = DrawText(hDC,m_item[index].m_text,
							strlen(m_item[index].m_text),&rc,
							DT_CALCRECT/*|DT_CENTER|DT_NOCLIP|DT_SINGLELINE*/);
					s.cx = rc.right + 12;
						
					SetRect(&m_item[index].m_rect,
							m_item[index-1].m_rect.left,
							m_item[index-1].m_rect.bottom,
							m_item[index-1].m_rect.left + s.cy + 8,
							m_item[index-1].m_rect.bottom + s.cx);
					m_BarSize.cy = max(m_BarSize.cy,m_item[index].m_rect.bottom);
					m_BtnsSize.cy += s.cx;
				}
			}
			m_WndSize.cx = m_BarSize.cx;
		}
		else
		{
			SelectObject(hDC,m_font.GetFont());
			
			m_nMinWidth = EndSize();

			if(m_item->m_text)
			{
				s.cy = DrawText(hDC,m_item->m_text,strlen(m_item->m_text),&rc,DT_CALCRECT);
				s.cx = rc.right + 12;
				SetRect(&m_item->m_rect,nIconSize,0,nIconSize + s.cx,s.cy + 8);
			}
			m_BarSize.cx = s.cx + nIconSize;
			m_BarSize.cy = s.cy + 8;
			m_nMinWidth = max(s.cx + nIconSize,m_nMinWidth);
		
			if(state == TBS_FLAG_FLY)
			{
				if(m_fSize.cy > GetHorzLineHeight())
					m_WndSize.cx = m_dockbar->GetClientWidth(m_fSize.cx + nIconSize);
				else
					m_WndSize.cx = m_dockbar->GetClientWidth(m_fSize.cx + nIconSize + ext);
			}
			else
				m_WndSize.cx = m_dockbar->GetClientWidth(0);

			for(;index<m_nBtnCount;index ++)
			{
				if(m_item[index].m_text)
				{
					SetRectEmpty(&rc);
					s.cy = DrawText(hDC,m_item[index].m_text,
										strlen(m_item[index].m_text),
										&rc,DT_CALCRECT);
					s.cx = rc.right + 12;

					SetRect(&m_item[index].m_rect,
								m_item[index-1].m_rect.right,
								m_item[index-1].m_rect.top,
								m_item[index-1].m_rect.right + s.cx,
								m_item[index-1].m_rect.top + s.cy + 8);
					m_nMinWidth = max(s.cx,m_nMinWidth);
				}

				if((m_item[index].m_rect.right) >= m_WndSize.cx)
				{
					//wrap
					OffsetRect(&m_item[index].m_rect,
							- m_item[index].m_rect.left,
							m_item[index].m_rect.bottom - m_item[index].m_rect.top);
					m_BarSize.cy += s.cy + 8;
				}
				m_BarSize.cx = max(m_BarSize.cx,m_item[index].m_rect.right);
			}
			if(m_item[m_nBtnCount-1].m_rect.right + ext >= m_WndSize.cx)
				m_BarSize.cy += s.cy + 8;
			else
				m_BarSize.cx += ext;
			
			m_BtnsSize.cx = min(m_BarSize.cx + ext,m_WndSize.cx);
			m_WndSize.cy = m_BarSize.cy;
		}
		ReleaseDC(m_hWnd,hDC);
	}
}

//计算按钮横向排列尺寸
int RingMenuBar::GetBtnsWidth()
{
	HDC hDC = GetDC(m_hWnd);	
	RECT rc = {0,0,0,0};
	
	SelectObject(hDC,m_font.GetFont());
			
	if(m_item->m_text)
	{
		DrawText(hDC,m_item->m_text,strlen(m_item->m_text),&rc,DT_CALCRECT);
		m_BtnsSize.cx = rc.right + 12 + PreSize();
	}
	for(int i=1;i<m_nBtnCount;i++)
	{
		if(m_item[i].m_text)
		{
			DrawText(hDC,m_item[i].m_text,strlen(m_item[i].m_text),&rc,DT_CALCRECT);
			m_BtnsSize.cx += rc.right + 12;
		}
	}
	m_BtnsSize.cx += EndSize();
	ReleaseDC(m_hWnd,hDC);
	return m_BtnsSize.cx;
}

//计算按钮纵向排列尺寸
int RingMenuBar::GetBtnsHeight()
{
	int ext = EndSize();
	int nIconSize = PreSize();
	HDC hDC = GetDC(m_hWnd);	
	RECT rc = {0,0,0,0};
	
	SelectObject(hDC,m_vfont.GetFont());
			
	if(m_item->m_text)
	{
		DrawText(hDC,m_item->m_text,strlen(m_item->m_text),&rc,DT_CALCRECT);
		m_BtnsSize.cy = rc.right + 12 + PreSize();
	}
	for(int i=1;i<m_nBtnCount;i++)
	{
		if(m_item[i].m_text)
		{
			DrawText(hDC,m_item[i].m_text,strlen(m_item[i].m_text),	&rc,DT_CALCRECT);
			m_BtnsSize.cy += rc.right + 12;
		}		
	}
	ReleaseDC(m_hWnd,hDC);
	m_BtnsSize.cy += EndSize();
	return m_BtnsSize.cy;
}

//获取单列菜单栏宽度
int RingMenuBar::GetVertLineWidth()
{
	if(m_SingleSize.cx == 0)
	{
		HDC hDC = GetDC(m_hWnd);	
		RECT rc = {0,0,0,0};
			
		SelectObject(hDC,m_vfont.GetFont());
			
		if(m_item && m_item->m_text)
		{
			DrawText(hDC,m_item->m_text,strlen(m_item->m_text),&rc,DT_CALCRECT);
			m_SingleSize.cx = rc.bottom + 8;
		}
		ReleaseDC(m_hWnd,hDC);
	}
	return m_SingleSize.cx;
}

//获取单行菜单栏高度
int RingMenuBar::GetHorzLineHeight()
{
	if(m_SingleSize.cy == 0)
	{
		HDC hDC = GetDC(m_hWnd);	
		RECT rc = {0,0,0,0};
			
		SelectObject(hDC,m_font.GetFont());
			
		if(m_item && m_item->m_text)
		{
			DrawText(hDC,m_item->m_text,strlen(m_item->m_text),&rc,DT_CALCRECT);
			m_SingleSize.cy = rc.bottom + 8;
		}
		ReleaseDC(m_hWnd,hDC);
	}
	return m_SingleSize.cy;
}

BOOL RingMenuBar::OnGetDragRects(int state,LPRECT lprc)
{
	if(lprc && m_dockbar)
	{
		lprc->left = lprc->top = 0;

		switch(state)
		{
		case TBS_FLAG_FLY:
			if(m_fSize.cx == 0 || m_fSize.cy == 0)
			{
				//初始化浮动矩形,为单行矩形
				m_fSize.cx = GetBtnsWidth();
				m_fSize.cy = GetHorzLineHeight();
			}
			lprc->right = m_fSize.cx;
			lprc->bottom = m_fSize.cy;
			break;
		case TBS_FLAG_HORZ:
			if(m_dockbar->IsVert())
			{
				lprc->right = GetBtnsWidth();
				lprc->bottom = m_BarSize.cx;
			}
			else
			{
				lprc->right = m_WndSize.cx;
				lprc->bottom = m_BarSize.cy;
			}
			break;
		case TBS_FLAG_VERT:
			if(m_dockbar->IsVert())
			{
				lprc->right = m_BarSize.cx;
				lprc->bottom = m_WndSize.cy;
			}
			else
			{
				lprc->bottom = GetBtnsHeight();
				//if(m_item)
				//	lprc->right = m_item->m_rect.bottom - m_item->m_rect.top;
				//else
					lprc->right = m_BarSize.cy;
			}
			break;
		case TBS_FLAG_DOCKBOTTOM:
			//获取整行高
			lprc->right = GetBtnsWidth();
			lprc->bottom = GetHorzLineHeight();
			break;
		case TBS_FLAG_DOCKRIGHT:
			//获取整列宽
			lprc->right = GetVertLineWidth();
			lprc->bottom = GetBtnsHeight();
			break;
		}
		return TRUE;
	}
	return FALSE;
}

int RingMenuBar::OnDockStateChange(int stateOld,int stateNew)
{
	Update();

	if(IsFloat(stateNew))
		SetPos(0,0,m_BarSize.cx,m_BarSize.cy,NULL,SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW);
	else
		SetPos(0,0,m_WndSize.cx,m_WndSize.cy,NULL,SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOREDRAW);
	return TRUE;
}

LRESULT RingMenuBar::RingdowProc(HWND hWnd,RINGPARAMS param)
{	
	switch(param.uMsg)
	{
		case WM_LBUTTONDOWN:
			return OnLButtonDown(param);
		case WM_MOUSEMOVE:
			return OnMouseMove(param);			
		case WM_LBUTTONUP:
			return OnLButtonUp(param);
		case WM_RBUTTONDOWN:
			return OnRButtonDown(param);
		case WM_SIZING:
			if(m_dockbar)
				return OnSizing(param);
		case WM_GETDRAGRECTS:
			if(param.lpnmhdr->hwndFrom == m_hWnd)
				return OnGetDragRects(param.lpnmhdr->code,(LPRECT)param.wParam);
		case WM_DOCKSTATECHANGE:
			return OnDockStateChange(param.shortval.low,param.shortval.high);
		//case WM_ERASEBKGND:
		case WM_PAINT:
			return OnPaint(param);
		case TB_HITTEST:
			return OnHitTest(param);
		case WM_MOUSELEAVE:
			if(m_nPopupedMenu == -1)
				PressButton(m_nHotButton,FALSE);
			m_nHotButton = -1;
			return 0;
		case WM_COMMAND:
			m_nPopupedMenu = -1;
			//don't break;
		case WM_MENUSELECT:
			return SendMessage(m_parent->Handle(),param);
		case WM_TIMER:
			return OnTimer(param);
		case WM_MEASUREITEM:      	
			if(m_rm)
   			m_rm->MeasureItem(param.lpmeasureitem);
         break;
      case WM_DRAWITEM:
			if(m_rm)
   			m_rm->Draw(param.lpdrawitem);
         break;
		case WM_ENTERMENULOOP:
			//弹出菜单,需要压下按钮,启动定时器监视鼠标动作
			PressButton(m_nPopupedMenu,TRUE);
			SetTimer(m_hWnd,1,10,NULL);
			break;
		case WM_EXITMENULOOP:
			//菜单关闭,需要弹起按钮,关闭定时器
			PressButton(m_nPopupedMenu,FALSE);
			KillTimer(m_hWnd,1);
			m_nPopupedMenu = -1;
			//按钮按下后选择菜单项,因为在菜单栏外点击,无法得到
			//WM_LBUTTONUP消息,导致工具栏被菜单遮盖的按钮无法显示,
			//因此需要让菜单栏重画。
			InvalidateRect(m_hWnd,NULL,FALSE);

			//未解决BUG:如果是BUTTON,即无菜单弹出,则不会收到
			//本消息,工具栏外点击则无法弹起按钮
			//解决思路:检测到该BUTTON,按下后SetCapture,OnTimer中
			//检测移到有菜单的按钮时ReleaseCapture,Capture到
			//鼠标按键消息ReleaseCapture,然后进行本消息完成功能
			//的处理,需要保证SetCapture和ReleaseCapture及时且正确。
			//留待以后解决,毕竟该BUG仅在根菜单中有非弹出菜单项且
			//选中该菜单项并在菜单栏外按下鼠标键才会发生。调用者
			//注意编辑资源时确保根菜单中无非弹出菜单项则可避免该BUG。			
			break;
		case MYWM_ICON:
			//定时器检测到菜单弹出,然后鼠标移动到别的按钮,
			//发送事件到该消息
			////发送到该消息的m_nPopupedMenu总为合法值
			if(m_rm && m_dockbar)
			{				
				PressButton(m_nPopupedMenu,FALSE);
				m_nPopupedMenu = param.wParam;

				RECT rc = {0,0,16,16};
				ClientToScreen(m_hWnd,(LPPOINT)&rc);
				ClientToScreen(m_hWnd,(LPPOINT)&rc+1);

				if(m_nPopupedMenu == MBAR_SYSICONSEL)
				{
					if(m_rmsys)
						m_rmsys->PopupEx(m_hWnd,rc.left,rc.top,m_dockbar->IsVert(),&rc);
					return 0;
				}
								
				GetButtonRect(param.wParam,&rc);
				ClientToScreen(m_hWnd,(LPPOINT)&rc);
				ClientToScreen(m_hWnd,(LPPOINT)&rc+1);				
				
				if(m_item[m_nPopupedMenu].m_data >= 0xFFFFFF00)	//有菜单
					m_rm->SubMenu(m_item[m_nPopupedMenu].m_data & 0xFF)->PopupEx(m_hWnd,rc.left,rc.top,m_dockbar->IsVert(),&rc);
				else
				{
					//是菜单项,无弹出菜单,因此不会触发WM_ENTERMENULOOP
					//消息,做WM_ENTERMENULOOP中完成的工作
					PressButton(m_nPopupedMenu,TRUE);
					SetTimer(m_hWnd,1,10,NULL);
				}
			}
			return 0;		
	}
	return DefaultProc(param);
}

LRESULT RingMenuBar::OnHitTest(RINGPARAMS& param)
{
	LPPOINT pt = (LPPOINT)param.lParam;
	if(m_item)
		for(int i=0;i<m_nBtnCount;i++)
		{
			if(PtInRect(&m_item[i].m_rect,*pt))
				return i;
		}
	return -1;
}

LRESULT RingMenuBar::OnLButtonDown(RINGPARAMS& param)
{	
	if(m_nPopupedMenu != -1)
	{
		//如果菜单中有非弹出菜单项,鼠标移动中使该按钮呈按下状态,
		//然后鼠标移出菜单栏点击,该按钮仍为按下状态。以下代码
		//作为补救措施处理该情况。
		PressButton(m_nPopupedMenu,FALSE);
		m_nPopupedMenu = -1;
		KillTimer(m_hWnd,1);
	}

	POINT pt = {param.mousept.x,param.mousept.y};
		
	int n = SendMessage(m_hWnd,TB_HITTEST,0,(LPARAM)&pt);

	if(m_nPopupedMenu == n && n != -1)
	{
		m_nPopupedMenu = -1;
		return 0;
	}

	if(n < 0 || n >= GetButtonCount())
	{
		if(m_hbmSys && m_bShowIcon)
		{
			n = CheckInExtButton(&pt,TRUE);
			if(n == MBAR_SYSICONSEL)
			{
				//按下图标或最小化/还原/关闭按钮
				m_nPopupedMenu = MBAR_SYSICONSEL;
				PostMessage(m_hWnd,MYWM_ICON,m_nPopupedMenu,0);
				return 0;
			}
			else if(n != 0)
			{
				SetCapture(m_hWnd);
				m_nCapedExtButton = n | 0x10000;
				PressExtButton(n,TRUE);
				return 0;
			}
		}
		else
		{
			if(m_dockbar && m_dockbar->m_pSite)
			{
				MapWindowPoints(m_hWnd,m_dockbar->m_pSite->Handle(),&pt,1);
				param.mousept.x = (short)pt.x;
				param.mousept.y = (short)pt.y;
				PostMessage(m_dockbar->m_pSite->Handle(),WM_LBUTTONDOWN,param.wParam,param.lParam);
				return 0;
			}
		}
	}

	if(m_rm && m_dockbar)
	{
		RECT rc;
		if(GetButtonRect(n,&rc))
		{
			ClientToScreen(m_hWnd,(LPPOINT)&rc);
			ClientToScreen(m_hWnd,(LPPOINT)&rc+1);
			m_nPopupedMenu = n;			
			
			if(m_item[n].m_data >= 0xFFFFFF00)	//有菜单
				m_rm->SubMenu(m_item[n].m_data & 0xFF)->PopupEx(m_hWnd,rc.left,rc.top,m_dockbar->IsVert(),&rc);
			else
				PressButton(n);
		}
	}	
	return 0;
}

LRESULT RingMenuBar::OnMouseMove(RINGPARAMS& param)
{
	if(m_nCapedExtButton != 0)
	{
		POINT pt = {param.mousept.x,param.mousept.y};
		int n = CheckInExtButton(&pt,TRUE);
		
		if(m_nCapedExtButton < 0x10000 && n == (int)m_nCapedExtButton)
		{
			//监视的按钮未按下,鼠标移到该按钮
			m_nCapedExtButton |= 0x10000;
			PressExtButton(n,TRUE);
		}
		else if(m_nCapedExtButton > 0x10000 && n != LOWORD(m_nCapedExtButton))
		{
			//监视的按钮已按下,鼠标移出该按钮
			m_nCapedExtButton &= 0xFFFF;
			PressExtButton(m_nCapedExtButton,FALSE);
		}
	}	
	//if(!m_dragger.IsDragging())
	{
		POINT pt = {param.mousept.x,param.mousept.y};
		param.lParam = (LONG)&pt;
		if(SetHotButton(OnHitTest(param)))
		{
			TRACKMOUSEEVENT tme;
			
			tme.cbSize = sizeof(TRACKMOUSEEVENT);
			tme.dwFlags = TME_LEAVE;
			tme.hwndTrack = m_hWnd;
			TrackMouseEvent(&tme);
		}
		return 0;		
	}

	return DefaultProc(param);
	//return RingDockBar::OnMouseMove(param);
}

LRESULT RingMenuBar::OnLButtonUp(RINGPARAMS& param)
{	
//	if(m_dragger.IsDragging())
//		return RingDockBar::OnLButtonUp(param);

	if(m_nCapedExtButton)
	{
		ReleaseCapture();
		POINT pt = {param.mousept.x,param.mousept.y};
		int n = CheckInExtButton(&pt,TRUE);
		if(n == (int)(m_nCapedExtButton & 0xFFFF))
		{
			PressExtButton(n,FALSE);
			switch(n)
			{
				case MBAR_SYSMINSEL:
					((RingMDIFrameWnd*)m_parent)->MinChild();
					break;
				case MBAR_SYSRESTORESEL:
					((RingMDIFrameWnd*)m_parent)->RestoreChild();
					break;
				case MBAR_SYSCLOSESEL:
					((RingMDIFrameWnd*)m_parent)->CloseChild();
					break;
			}			
		}
		m_nCapedExtButton = 0;
		return 0;
	}
	//else
	//	return RingDockBar::OnLButtonUp(param);

	if(m_nPopupedMenu >= 0 && m_nPopupedMenu < m_nBtnCount
		&& m_item)
	{
		if(m_item[m_nPopupedMenu].m_data >= 0xFFFFFF00)
			m_nPopupedMenu = -1;
		else
		{
			//按钮无弹出菜单,需要先设置正确的按钮命令ID,发送完命令
			//(DefaultProc处理)后再置回按钮ID,以确保后续的按下按钮
			//后鼠标在按钮间移动能正确检测到该按钮。
			SendMessage(m_parent->Handle(),WM_COMMAND,m_item[m_nPopupedMenu].m_data,(LPARAM)m_hWnd);
			PressButton(m_nPopupedMenu,FALSE);
			m_nPopupedMenu = -1;			
		}
	}

	return 0;
}

LRESULT RingMenuBar::OnRButtonDown(RINGPARAMS& param)
{	
	if(m_nPopupedMenu != -1)
	{
		//如果菜单中有非弹出菜单项,鼠标移动中使该按钮呈按下状态,
		//然后鼠标移出菜单栏点击,该按钮仍为按下状态。以下代码
		//作为补救措施处理该情况。
		PressButton(m_nPopupedMenu,FALSE);
		m_nPopupedMenu = -1;
		KillTimer(m_hWnd,1);
	}
	
	POINT pt = {param.mousept.x,param.mousept.y};
	
	if(m_dockbar && m_dockbar->m_pSite)
	{
		MapWindowPoints(m_hWnd,m_dockbar->m_pSite->Handle(),&pt,1);
		param.mousept.x = (short)pt.x;
		param.mousept.y = (short)pt.y;
		return SendMessage(m_dockbar->m_pSite->Handle(),param);
	}
	return 0;
}

LRESULT RingMenuBar::OnTimer(RINGPARAMS& param)
{
	POINT pt;
	int n;
	GetCursorPos(&pt);
	
	//菜单栏折行,菜单弹出遮住其他按钮时需要判断是否在菜单上
	if(m_item && m_nPopupedMenu >= 0 && m_nPopupedMenu < GetButtonCount())
	{
		if(m_item[m_nPopupedMenu].m_data >= 0xFFFFFF00)	//有菜单
		{
			POINT ppt = {pt.x + 3,pt.y + 3};	//加上菜单边框
			n = MenuItemFromPoint(m_hWnd,
					m_rm->SubMenu(m_item[m_nPopupedMenu].m_data & 0xFF)->GetMenu(),
					ppt);
			if(n != -1)
				return 0;
		}
	}

	ScreenToClient(m_hWnd,&pt);
	n = SendMessage(m_hWnd,TB_HITTEST,0,(LPARAM)&pt);

	if(m_nPopupedMenu == -1 || n < 0 || n >= GetButtonCount())
		if(m_bShowIcon && CheckInExtButton(&pt) == MBAR_SYSICONSEL)
			n = MBAR_SYSICONSEL;
		else		
			return 0;

	if(n != m_nPopupedMenu)
	{	
		PostMessage(m_hWnd,WM_CANCELMODE,0,0);
		PostMessage(m_hWnd,MYWM_ICON,n,0);
	}
	
	return 0;
}

LRESULT RingMenuBar::OnSizing(RINGPARAMS& param)
{
	RECT rc;
	LPRECT lprc = (LPRECT)param.lParam;
	//param.lParam = (LPARAM)&rc;
	CopyRect(&rc,lprc);
	
	OffsetRect(lprc,-lprc->left,-lprc->top);
	lprc->right = max(m_nMinWidth,lprc->right);
	m_fSize.cx = lprc->right;
	m_fSize.cy = lprc->bottom;
	Update();
	
	lprc->right = m_BarSize.cx;
	lprc->bottom = m_BarSize.cy;
	m_fSize.cx = lprc->right;
	m_fSize.cy = lprc->bottom;
	
	MoveWindow(m_hWnd,0,0,m_fSize.cx,m_fSize.cy,FALSE);
	InvalidateRect(m_hWnd,NULL,TRUE);
	return TRUE;
}

BOOL RingMenuBar::GetButtonRect(int index,LPRECT lprect)
{
	if(lprect && index >= 0 && index < m_nBtnCount && m_item)
		return CopyRect(lprect,&m_item[index].m_rect);
	else
		return FALSE;
}

BOOL RingMenuBar::SetHotButton(int index)
{
	if(m_nHotButton == index && m_nHotButton != -1)
		return TRUE;

	PressButton(m_nHotButton,FALSE);
	m_nHotButton = -1;

	if(index >= 0 && index < m_nBtnCount && m_item)
	{
		HDC hDC = GetDC(m_hWnd);
		DrawEdge(hDC,&m_item[index].m_rect,BDR_RAISEDINNER,BF_RECT);//TOPLEFT);
		ReleaseDC(m_hWnd,hDC);

		m_nHotButton = index;
		return TRUE;
	}
	return FALSE;
}

void RingMenuBar::PressButton(int index,BOOL bPress/*=TRUE*/)
{
	if(index >= 0 && index < m_nBtnCount && m_item)
	{
		if(bPress)
			m_item[index].m_state |= TBSTATE_PRESSED;
		else
			m_item[index].m_state &= ~TBSTATE_PRESSED;
		InvalidateRect(m_hWnd,&m_item[index].m_rect,TRUE);		
	}
}

//判断鼠标位置位于系统图标,最小化,还原,关闭按钮哪个位置
//调用此函数前应判断菜单栏是否显示了这些按钮
//传入参数的坐标为相对于本窗口的坐标
//bCheckAll:是否仅判断系统图标
int RingMenuBar::CheckInExtButton(LPPOINT lpMousePt,BOOL bCheckAll/*=FALSE*/)
{
	RECT rc = {0,0,16,16};
	POINT pt = {lpMousePt->x,lpMousePt->y};
	int res = 0;
	
	if(PtInRect(&rc,pt))
		return MBAR_SYSICONSEL;
		
	if(bCheckAll)// && PtInRect(&m_rcSysBtn,pt))
	{
		int ch = pt.x - m_rcSysBtn.left;
		CopyRect(&rc,&m_rcSysBtn);

		if(m_dockbar && m_dockbar->IsVert())
		{			
			rc.left = m_rcSysBtn.right - 16;
			rc.top = m_rcSysBtn.bottom - 50;
			ch = pt.y - rc.top;
		}
		
		if(PtInRect(&rc,pt) && (ch < 32 || ch > 34))	//不在还原与关闭按钮间的空挡
			return (ch / 16) + MBAR_SYSMINSEL;
	}

	return -1;
}

void RingMenuBar::PressExtButton(UINT uID,BOOL bPress)
{
	if(uID < MBAR_SYSMINSEL || uID > MBAR_SYSCLOSESEL)
		;//PressButton(uID,bPress);
	else
	{
		//按下,弹起最小化,还原,关闭按钮
		HDC hdc = GetDC(m_hWnd);
		HDC hMemDC = CreateCompatibleDC(hdc);
		SelectObject(hMemDC,m_hbmSys);

		RECT rc = {0,3,16,17};
		int offsetx,offsety;
		int xpos = (uID - MBAR_SYSMINSEL) * 16 + 36;

		if(m_dockbar && m_dockbar->IsVert())
		{
			offsetx = m_rcSysBtn.right - rc.right;
			offsety = (uID - MBAR_SYSMINSEL)*16 + m_rcSysBtn.bottom - 48 - rc.top;
			if(uID == MBAR_SYSCLOSESEL)
			{
				offsety += 2;
				xpos += 2;
			}			
		}
		else
		{
			offsetx = (uID - MBAR_SYSMINSEL)*16 + m_rcSysBtn.left;
			offsety = m_rcSysBtn.top - rc.top;
			if(uID == MBAR_SYSCLOSESEL)
			{
				offsetx += 2;
				xpos += 2;
			}
		}
		OffsetRect(&rc,offsetx,offsety);

		BitBlt(hdc,rc.left,rc.top,16,14,hMemDC,xpos,0,SRCCOPY);

		if(bPress)
		{
			BitBlt(hdc,rc.left+3,rc.top+2,12,12,hMemDC,(uID - MBAR_SYSMINSEL) * 12,0,SRCAND);
			DrawEdge(hdc,&rc,EDGE_SUNKEN,BF_TOPLEFT);
			DrawEdge(hdc,&rc,BDR_SUNKENINNER,BF_BOTTOMRIGHT);			
		}
		else
		{
			BitBlt(hdc,rc.left+2,rc.top+1,12,12,hMemDC,(uID - MBAR_SYSMINSEL) * 12,0,SRCAND);
			DrawEdge(hdc,&rc,BDR_RAISEDINNER,BF_TOPLEFT);
			DrawEdge(hdc,&rc,EDGE_RAISED,BF_BOTTOMRIGHT);
		}
		DeleteDC(hMemDC);
		ReleaseDC(m_hWnd,hdc);
	}

}

LRESULT RingMenuBar::OnPaint(RINGPARAMS& param)
{
	//OnEraseBkg(param);
		
	PAINTSTRUCT ps;
	RECT rc;
	BeginPaint(m_hWnd,&ps);
	if(m_dockbar)
		m_dockbar->DrawBkg(ps.hdc);
	//ps.hdc = param.hdc;

	SetBkMode(ps.hdc,TRANSPARENT);
		
	if(m_dockbar && m_dockbar->IsVert())
		SelectObject(ps.hdc,m_vfont.GetFont());
	else
		SelectObject(ps.hdc,m_font.GetFont());

	for(int i=0;i<=m_nBtnCount;i++)
	{
		if(m_item[i].m_text)
		{
			CopyRect(&rc,&m_item[i].m_rect);
			if((m_item[i].m_state & TBSTATE_PRESSED) == TBSTATE_PRESSED)
			{
				DrawEdge(ps.hdc,&rc,BDR_SUNKENOUTER,BF_RECT);
				OffsetRect(&rc,1,1);
			}
			if(m_dockbar && m_dockbar->IsVert())
				TextOut(ps.hdc,rc.right-4,rc.top+6,m_item[i].m_text,strlen(m_item[i].m_text));
			else
				DrawText(ps.hdc,m_item[i].m_text,-1,&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
		}			
	}
	
	DrawExtButton(ps.hdc);	
	EndPaint(m_hWnd,&ps);	

	return 0;
}

//绘制图标,最小化,还原,关闭按钮
void RingMenuBar::DrawExtButton(HDC hdc)
{
	if(m_hbmSys && m_bShowIcon)
	{
		HDC hMemDC = CreateCompatibleDC(hdc);
		SelectObject(hMemDC,m_hbmSys);
		
		if(m_parent->GetWindowType() == ITIS_MDIFRAME)
		{
			HWND hwnd = ((RingMDIFrameWnd*)m_parent)->GetCurrChildWnd();
			m_sysIcon = (HICON)SendMessage(hwnd,WM_GETICON,ICON_SMALL,0);
		}
		//无图标,载入默认图标
		if(m_sysIcon == NULL)
			m_sysIcon = LoadIcon(NULL,IDI_WINLOGO);
		DrawIconEx(hdc,0,0,m_sysIcon,16,16,0,NULL,DI_NORMAL);
		
		RECT rc;

		::GetClientRect(m_hWnd,&rc);
		//将按钮坐标移到与窗口坐标右对齐
		OffsetRect(&m_rcSysBtn,rc.right - m_rcSysBtn.right,rc.bottom - 3 - m_rcSysBtn.bottom);
		BitBlt(hMemDC,36,0,50,14,hdc,m_rcSysBtn.left,m_rcSysBtn.top,SRCCOPY);

		rc.right = rc.right - rc.left - 34;
		rc.left = rc.right - 16;
		rc.top = m_rcSysBtn.top;
		rc.bottom = m_rcSysBtn.bottom;

		int offx1,offy1,offx2,offy2;

		if(m_dockbar && m_dockbar->IsVert())
		{
			OffsetRect(&rc,34,-34);
			//最小化按钮,+2
			BitBlt(hdc,rc.left+2,rc.top+1,12,12,hMemDC,0,0,SRCAND);
			//还原按钮,+16+2
			BitBlt(hdc,rc.left+2,rc.top+17,12,12,hMemDC,12,0,SRCAND);
			//关闭按钮,+32+2(该按钮与还原按钮相距空间)+2
			BitBlt(hdc,rc.left+2,rc.top+35,12,12,hMemDC,24,0,SRCAND);
			
			offx1 = offx2 = 0;
			offy1 = 16;
			offy2 = 18;
		}
		else
		{
			//最小化按钮,+2
			BitBlt(hdc,m_rcSysBtn.left+2,m_rcSysBtn.top+1,12,12,hMemDC,0,0,SRCAND);
			//还原按钮,+16+2
			BitBlt(hdc,m_rcSysBtn.left+18,m_rcSysBtn.top+1,12,12,hMemDC,12,0,SRCAND);
			//关闭按钮,+32+2(该按钮与还原按钮相距空间)+2
			BitBlt(hdc,m_rcSysBtn.left+36,m_rcSysBtn.top+1,12,12,hMemDC,24,0,SRCAND);
			offy1 = offy2 = 0;
			offx1 = 16;
			offx2 = 18;
		}
		
		DeleteDC(hMemDC);

		DrawEdge(hdc,&rc,BDR_RAISEDINNER,BF_TOPLEFT);
		DrawEdge(hdc,&rc,EDGE_RAISED,BF_BOTTOMRIGHT);
		OffsetRect(&rc,offx1,offy1);
		DrawEdge(hdc,&rc,BDR_RAISEDINNER,BF_TOPLEFT);
		DrawEdge(hdc,&rc,EDGE_RAISED,BF_BOTTOMRIGHT);
		OffsetRect(&rc,offx2,offy2);
		DrawEdge(hdc,&rc,BDR_RAISEDINNER,BF_TOPLEFT);
		DrawEdge(hdc,&rc,EDGE_RAISED,BF_BOTTOMRIGHT);
	}
}

LRESULT RingMenuBar::OnNotify(RINGPARAMS& param)
{
	//不需要TOOLTIP
	return DefaultProc(param);
}

//hWnd是父窗口的HWND
BOOL RingMenuBar::OnParentNotify(HWND hWnd,UINT uMsg,UINT wParam,LONG lParam)
{	
   if(uMsg == MYWM_SIZE)
	{
		Update();
		InvalidateRect(m_hWnd,NULL,TRUE);
		if(IsVert(lParam))
			return m_BarSize.cx;//CalcReSizeV(wParam);
		else
			return m_BarSize.cy;//CalcReSizeH(wParam);
	}
	return FALSE;
}

void RingMenuBar::SetSysControlInfo(BOOL m_bChildMax)
{
	m_bShowIcon = m_bChildMax;

	if(m_rmsys == NULL)
		m_rmsys = new RingMenu;		
	
	if(m_rmsys)
	{
		HWND hwnd = ((RingMDIFrameWnd*)m_parent)->GetCurrChildWnd();
		if(hwnd)
		{
			m_rmsys->Detach();
			m_rmsys->Attach(GetSystemMenu(hwnd,FALSE));
		}
	}
	
	if(m_dockbar)
		m_dockbar->UpdateAllSite();
}